<template>
  <div class="container">
    <p>你好</p>
    {{ reverseMsg }}
    <button @click="countAdd">增加</button>
  </div>
</template>

<script setup>
import { computed, ref, watchEffect } from 'vue';

const msg = 'hello world'
// 处理复杂逻辑：将一些复杂的逻辑写在js中，简化模版代码
const reverseMsg = computed(() => msg.split('').reverse().join(''))
// 有缓存：当对应的依赖没有发生改变的时候，相应的计算属性也不会发生变化，会使用缓存的值
// 本质：computed本质就是get函数返回一个具有ref属性的值，也是通过.value解包拿到对应值的，但是它和ref的区别就是自动追踪状态更新，而ref不会
const num1 = ref(1);
const num2 = ref(2);
const sum = ref(num1.value + num2.value);
const comSum = computed(() => num1.value + num2.value)
console.log(sum.value);  // 当num发生变化的时候，通过ref声明的变量不会自动发生更新，但是computed方式声明的依赖会对应更新，在devtools中可以调试看到结果
console.log(comSum.value);
// 特点：只读
// comSum.value = 888 // 报黄
// console.log(comSum.value); // 报黄

// 计算属性由其性质决定了它不支持异步代码，因为它是声明派生数据的一个方法，如果数据发生改变而它是异步改变的，则违背自动追踪依赖更新的性质
const asyncSum = computed(() => {
  console.log("♥ Hello ♥"); // 同步代码--打印了
  setTimeout(() => {
    // 异步操作，不应该在计算属性中使用
    console.log("♥ Hello ♥");  // 异步代码--未打印
    return num2.value * 2;
  }, 1000);
})
console.log(asyncSum.value); // undefined


// watchEffect 相关，当被监听的数据源在回调中也使用到了，那么就会自动执行监听且会立即执行，是watch的一种简写方式
let count = ref(0);
let count2 = ref(10);
const countAdd = () => {
  count.value++;
  // count2.value++;
}
watchEffect(() => {
  console.log(count.value, count2.value)
})

</script>

<style scoped></style>